package beer.coder.awesome.sboot.system.health.service;

import beer.coder.awesome.sboot.system.health.entity.MonitorData;
import org.springframework.stereotype.Service;
import oshi.SystemInfo;
import oshi.hardware.CentralProcessor;
import oshi.hardware.HardwareAbstractionLayer;
import oshi.software.os.OperatingSystem;

import javax.annotation.PostConstruct;

@Service
public class MonitorService {
    static final long MB = 1024 * 1024;
    SystemInfo systemInfo;
    OperatingSystem os;
    HardwareAbstractionLayer hal;
    private volatile long[] oldTicks = null;

    @PostConstruct
    public void init() {
        systemInfo = new SystemInfo();
        os = systemInfo.getOperatingSystem();
        hal = systemInfo.getHardware();
        oldTicks = new long[CentralProcessor.TickType.values().length];
    }

    public MonitorData retrieveMonitorData() {
        MonitorData monitorData = new MonitorData();
        monitorData.setMachine(retrieveMachineName());
        monitorData.setJvmMemory(1.0 * retrieveJvmMemory() / MB);
        monitorData.setJvmMemoryUnit("MB");
        monitorData.setMemoryUsage(retrieveMemoryUsage());
        monitorData.setCpuUsage(retrieveCpuUsage());
        monitorData.setProcessId(retrievePid());
        return monitorData;
    }

    protected int retrievePid() {
        return os.getProcessId();
    }

    protected String retrieveMachineName() {
        return os.getNetworkParams().getHostName();
    }

    protected long retrieveJvmMemory() {
        return os.getProcess(retrievePid()).getResidentSetSize();
    }


    protected double retrieveCpuUsage() {
        CentralProcessor processor = hal.getProcessor();
        double usage = processor.getSystemCpuLoadBetweenTicks(oldTicks);
        oldTicks = processor.getSystemCpuLoadTicks();

        return usage;
    }


    protected double retrieveMemoryUsage() {
        long totalMemory = hal.getMemory().getTotal();
        long usageMemory = totalMemory - hal.getMemory().getAvailable();

        return 1.0 * usageMemory / totalMemory;
    }
}
